
package com.controller;


import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.Producer.RedisCacheProducer;
import com.alibaba.fastjson.JSONObject;
import com.constant.AuthConstant;
import com.domain.dto.MaintenanceManDTO;
import com.domain.dto.SendCodeDTO;
import com.domain.dto.TokenRedisDTO;
import com.domain.dto.UserDTO;
import com.domain.entity.TokenEntity;
import com.domain.entity.WeixiuyuanEntity;
import com.domain.vo.UserVO;
import com.exception.ErrorCode.AuthErrorCode;
import com.exception.ErrorCode.UserErrorCode;
import com.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.domain.entity.UserEntity;
import com.service.TokenService;
import com.service.UserService;


@RequestMapping("users")
@RestController
@Slf4j
public class UserController{

	@Autowired
	private RedisClient redisClient;
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private TokenService tokenService;

	@Autowired
	private RedisCacheProducer redisCacheProducer;

	@Autowired
	private MailUtils mailUtils;

	/**
	 * 登录
	 */
	@IgnoreAuth
	@PostMapping(value = "/login")
	public R login(String username, String password) {
		UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));
		//用户是否存在
		if (user == null) {
			return R.error(AuthErrorCode.USER_NOT_EXIST.getMessage());
		}

		//判断密码是否正确
		String salt = user.getSalt();
		String passwordHash = user.getPasswordHash();
		String NowPasswordHash = PasswordEncryptorUtil.encryptPassword(password, Base64.getDecoder().decode(salt));
		if (!passwordHash.equals(NowPasswordHash)) {
			return R.error(AuthErrorCode.USER_PASSWORD_ERROR.getMessage());
		}

		//生成token
		String token = JJwtUtils.createToken(user);

		//将token存入到数据库中
		tokenService.insertToken(user.getId(),username, "users", user.getRole(),token);
        log.info("管理员用户：{}登录成功", username);
		log.info("生成令牌：{}",token);

		return R.ok().put("token", token);
	}
	
	/**
	 * 注册
	 */
	@IgnoreAuth
	@PostMapping(value = "/register")
	public R register(@RequestBody UserDTO user){

    	if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {
    		return R.error(AuthErrorCode.USER_IS_EXIST.getMessage());
    	}

		byte[] salt = PasswordEncryptorUtil.getSalt();
		String encryptedPassword = PasswordEncryptorUtil.encryptPassword(user.getPassword(),salt);

		UserEntity userEntity = new UserEntity();
		BeanUtils.copyProperties(user,userEntity);
		userEntity.setSalt(Base64.getEncoder().encodeToString(salt));
		userEntity.setPasswordHash(encryptedPassword);
		userEntity.setId(new Date().getTime() + new Double(Math.floor(Math.random() * 1000)).longValue());

		userService.insert(userEntity);
        return R.ok();
    }

	/**
	 * 管理员退出登录
	 */
	@DeleteMapping(value = "logout")
	public R logout(HttpServletRequest request) {

		String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);
		String jsonInfo = redisClient.getString(AuthConstant.tokenPrefix + token);
		String userid = JSONObject.parseObject(jsonInfo, TokenRedisDTO.class).getUserid();
		//删除掉数据库中的数据
		tokenService.delete(new EntityWrapper<TokenEntity>().eq("userid", userid));

		return R.ok("退出成功");
	}

	/**
	 * 获取管理员个人信息
	 */
	@RequestMapping("/session")
	public R getCurrUser(HttpServletRequest request){
		//从redis中获取用户信息
		String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);
		String jsonInfo = redisClient.getString(AuthConstant.tokenPrefix + token);
		String id = JSONObject.parseObject(jsonInfo, TokenRedisDTO.class).getUserid();
		String json = redisClient.getString(AuthConstant.MAINTENANCEMAN_INFO_KEY + id);
		if (StringUtils.isNotEmpty(json)){

			UserVO userVO = JSONObject.parseObject(json, UserVO.class);
			//将数据返回给前端
			return R.ok().put("data", userVO);
		}

		//为空的话查询数据库
		UserEntity userEntity = userService.selectOne(new EntityWrapper<UserEntity>().eq("id", id));
		UserVO userVO = new UserVO();
		BeanUtils.copyProperties(userEntity, userVO);
		String jsonString = JSONObject.toJSONString(userVO);

		//将查询到的结果返回并且将结果存入到redis中
		redisCacheProducer.adminSendToKafka(String.valueOf(userVO.getId()),jsonString);

		return R.ok().put("data", userVO);

	}

	/**
	 * 修改管理员密码
	 */
	@PostMapping("/updatePassword")
	public R updatePassword(@RequestBody SendCodeDTO sendCodeDTO, HttpServletRequest request){
		String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);

		TokenRedisDTO tokenRedisDTO = JSONObject.parseObject(redisClient.getString(AuthConstant.tokenPrefix + token), TokenRedisDTO.class);

		//先判断验证码是否正确
		String redisCode = redisClient.getString(AuthConstant.ADMIN_INFO_CAPTCHA_PREFIX + tokenRedisDTO.getUserid());

		if(!sendCodeDTO.getCode().equals(redisCode)) {
			return R.error(422, UserErrorCode.CAPTCHA_CODE_INCORRECT.getMessage());
		}

		byte[] salt = PasswordEncryptorUtil.getSalt();
		String encryptPassword = PasswordEncryptorUtil.encryptPassword(sendCodeDTO.getNewPassword(), salt);

		UserEntity userEntity = new UserEntity();
		userEntity.setSalt(Base64.getEncoder().encodeToString(salt));
		userEntity.setPasswordHash(encryptPassword);
		userEntity.setId(Long.valueOf(tokenRedisDTO.getUserid()));

		//将盐和密码存入到数据库中
		userService.updateById(userEntity);

		//删掉redis中验证码缓存
		redisClient.deleteKey(AuthConstant.ADMIN_INFO_CAPTCHA_PREFIX + tokenRedisDTO.getUserid());

		return R.ok();
	}


	/**
	 * 发送验证码
	 */
	@GetMapping("/sendCode")
	public R sendCode(HttpServletRequest request){

		String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);

		TokenRedisDTO tokenRedisDTO = JSONObject.parseObject(redisClient.getString(AuthConstant.tokenPrefix + token), TokenRedisDTO.class);

		UserVO userVO = JSONObject.parseObject(redisClient.getString(AuthConstant.ADMIN_INFO_KEY + tokenRedisDTO.getUserid()), UserVO.class);
		//生成验证码
		String code = CaptchaUtil.generateCaptcha();

		//生成后将验证码存放到redis中有效器为15分钟
		redisClient.setMinString(AuthConstant.ADMIN_INFO_CAPTCHA_PREFIX + userVO.getId(),code,900L);

		String content = "[汽车充电桩管理系统]" + code + " 是你修改密码所需的验证码，不要和其他人分享，有效期为15分钟";

		mailUtils.sendMail(userVO.getEmail(),"汽车充电桩管理系统，用于修改密码所需的验证码",content);

		return R.ok();
	}


	/**
	 * 修改维修员信息
	 */
	@PostMapping("/updateInfo")
	public R updateInfo(@RequestBody UserDTO userDTO,HttpServletRequest request){
		String token = request.getHeader(AuthConstant.LOGIN_TOKEN_KEY);
		String tokenJson = redisClient.getString(AuthConstant.tokenPrefix + token);
		TokenRedisDTO tokenRedisDTO = JSONObject.parseObject(tokenJson, TokenRedisDTO.class);

		//直接修改数据库中数据
		UserEntity userEntity = new UserEntity();
		BeanUtils.copyProperties(userDTO, userEntity);
		userEntity.setId(Long.valueOf(tokenRedisDTO.getUserid()));

		userService.updateTokenAndUser(userEntity);

		return R.ok();

	}


    /**
     * 保存
     */
    @PostMapping("/save")
    public R save(@RequestBody UserEntity user){
    	if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {
    		return R.error("用户已存在");
    	}
        userService.insert(user);
        return R.ok();
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@RequestBody UserEntity user){

    	UserEntity u = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername()));

    	if(u!=null && u.getId()!=user.getId() && u.getUsername().equals(user.getUsername())) {
    		return R.error("用户名已存在。");
    	}
        userService.updateById(user);//全部更新
        return R.ok();
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    public R delete(@RequestBody Long[] ids){
        userService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    }
}
